package com.minning.protocol;

import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mysql.jdbc.StringUtils;

import java.sql.Connection;

public class ProtocolAnalysis {

	private static Connection conn = null;
	private static List<ProtocolBean> protocollist = null;
	private static Map<String, SignalsBean> signalmap = null;
	private static Map<String, List<BooleanItemBean>> booleanItemMap = null;
	private static Map<String, Map<String, SignalEnumBean>> signalEnumMap = null;
	// 输入信号StartAddress
	private static int startAddr = 0;
	// 信号包含Float个数
	private static int numOfFloat = 0;
	// 信号数据
	private static byte[] contentByte = null;
	// booleanset常量
	private static String BOOLEANSET = "booleanset";
	// int常量
	private static String INT = "int";
	// 枚举常量
	private static String ENUM = "枚举";

	private static Map<String, Object> signalNameUnitRMap = new HashMap<>();

	public static void main(String[] args) throws Exception {
		String url = "jdbc:mysql://localhost:3306/springmvcdb?"
				+ "user=root&password=root&useUnicode=true&characterEncoding=UTF8";

		try {
			Class.forName("com.mysql.jdbc.Driver");// 动态加载mysql驱动
			// System.out.println("成功加载MySQL驱动程序");
			conn = DriverManager.getConnection(url);
			// get the signal bean
			signalmap = ProtocolGetFromDb.selectFromSignals(conn);
			booleanItemMap = ProtocolGetFromDb.selectFromBooleansignal(conn, BOOLEANSET);

			signalEnumMap = ProtocolGetFromDb.selectFromSignalEnum(conn);
			// 从文件获得二进制数组
			byte[] tempbytelist = BinaryFileRead.ReadBinaryFile();
			startAddr = 0;
			numOfFloat = 26;
			contentByte = tempbytelist;
			// 检索指定的协议
			protocollist = ProtocolGetFromDb.selectFromProtocol(conn, startAddr);
			// 调用解析方法
			long startime = System.currentTimeMillis();
			Map<String,Map<String,Object>> result = getSignalStr();
			Map<String, Object> unitMap =result.get("values");
			for(String string: unitMap.keySet()){
				System.out.println(string + ":" + unitMap.get(string));
			}
			long endtime = System.currentTimeMillis();
			
			
			System.out.println(endtime - startime);
		} catch (SQLException e) {
			System.out.println("MySQL操作错误");
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			conn.close();
		}

	}

	public static Map<String, Map<String, Object>> getSignalStr() {
		// 当前解析信号的byte数组
		byte[] thisByteList;
		Map<String, Object> valuesMap = new HashMap<String, Object>();
		for (int i = 0; i < protocollist.size() && i < numOfFloat; i++) {
			int startbyte = 4 * (protocollist.get(i).getStartAddr() - startAddr);

			// 结束byte位置，仅float类型时，结束byte位置=起始byte位置+4
			int endbyte = 4 * (protocollist.get(i).getStartAddr() - startAddr) + 4;

			// 从所有数据数组里截取当前信号的byte数组
			thisByteList = Arrays.copyOfRange(contentByte, startbyte, endbyte);

			// byte数组转int
			int thisBit = ((thisByteList[0] & 0xff) << 24) | ((thisByteList[1] & 0xff) << 16)
					| ((thisByteList[2] & 0xff) << 8) | (thisByteList[3] & 0xff);

			// int类型（位）转float
			float f = Float.intBitsToFloat(thisBit);

			if (BOOLEANSET.equals(protocollist.get(i).getItemType())) {// booleanset的情况
				List<BooleanItemBean> booleanItemBeanList = booleanItemMap
						.get(String.valueOf(protocollist.get(i).getItemId()));
				// 分割booleanset成多个布尔信号
				for (int j = 0; j < booleanItemBeanList.size(); j++) {
					int booleanInt = (int) f;
					// boolean类型截位
					int booleanValue = getBit(booleanInt, booleanItemBeanList.get(j).getStartBit());
					// String outputStr =
					// signalmap.get(String.valueOf(booleanItemBeanList.get(j).getSignalId())).getSignalCNName()
					// + ":" +
					// signalEnumMap.get(String.valueOf(booleanItemBeanList.get(j).getSignalId())).get(String.valueOf(booleanValue)).getValue()
					// +
					// signalmap.get(String.valueOf(booleanItemBeanList.get(j).getSignalId())).getUnit()
					// + "\r\n";
					/*String outputStr = signalmap.get(String.valueOf(booleanItemBeanList.get(j).getSignalId()))
							.getSignalCNName() + ":" + booleanValue + "\r\n";*/
					// System.out.print(outputStr);

					valuesMap.put(
							signalmap.get(String.valueOf(booleanItemBeanList.get(j).getSignalId())).getSignalName(),
							booleanValue);
				}
			} else {// Signal的情况
				String signalvalue = null;
				String datatype = signalmap.get(String.valueOf(protocollist.get(i).getItemId())).getDataType();
				String signaltype = signalmap.get(String.valueOf(protocollist.get(i).getItemId())).getSignalType();
				if (INT.equals(datatype)) {
					signalvalue = String.valueOf((int) f);
				} else {
					signalvalue = String.valueOf(f);
				}
				if (ENUM.equals(signaltype)) {
					// 枚举值的转换signalEnumMap.get(信号ID).get(枚举key).getValue()
					signalvalue = signalEnumMap.get(String.valueOf(protocollist.get(i).getItemId()))
							.get(String.valueOf(signalvalue)).getValue();
					/*String outputStr = signalmap.get(String.valueOf(protocollist.get(i).getItemId())).getSignalCNName()
							+ ":" + signalvalue + "\r\n";*/
					// System.out.print(outputStr);

					valuesMap.put(signalmap.get(String.valueOf(protocollist.get(i).getItemId())).getSignalName(),
							signalvalue);

				} else {
					/*String outputStr = signalmap.get(String.valueOf(protocollist.get(i).getItemId())).getSignalCNName()
							+ ":" + signalvalue
							+ signalmap.get(String.valueOf(protocollist.get(i).getItemId())).getUnit() + "\r\n";*/
					// System.out.print(outputStr);
					valuesMap.put(signalmap.get(String.valueOf(protocollist.get(i).getItemId())).getSignalName(),
							signalvalue);
					String signalName = signalmap.get(String.valueOf(protocollist.get(i).getItemId())).getSignalName();
					if (!StringUtils.isNullOrEmpty(signalName) && !signalNameUnitRMap.containsKey(signalName)) {
						signalNameUnitRMap.put(signalName,
								signalmap.get(String.valueOf(protocollist.get(i).getItemId())).getUnit());
					}
				}
			}
		}

		Map<String, Map<String, Object>> map2 = new HashMap<>();
		map2.put("unit", signalNameUnitRMap);
		map2.put("values", valuesMap);
		return map2;
	}

	/**
	 * 
	 * @param date
	 *            输入数据
	 * @param position
	 *            位置
	 * @return 取int的指定位bit.0/1
	 */
	public static int getBit(int date, int position) {
		int booleanBit = 0;

		date = (date << 8 - (position + 1)) & 0x80;
		booleanBit = date >> 7;

		return booleanBit;
	}

}